﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling.Design;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling;
using VsxFactory.Modeling;

namespace VsxFactory.Modeling.VisualStudio
{
    public class DynamicElementTypeDescriptor : Microsoft.VisualStudio.Modeling.Design.ElementTypeDescriptor
    {
        public DynamicElementTypeDescriptor(ICustomTypeDescriptor parent, ModelElement selectedElement)
            : base(parent, selectedElement)
        {
        }

        /// <summary>
        /// Sets to read only.
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="propertyInfoId">The property info id.</param>
        /// <param name="value">if set to <c>true</c> [value].</param>
        protected void SetReadOnly(PropertyDescriptorCollection properties, Guid propertyInfoId)
        {
            var propertyDescriptor = FindPropertyDescriptoy(properties, propertyInfoId) as ElementPropertyDescriptor;
            Guard.AssumeNotNull(propertyDescriptor, "propertyDescriptor");

            List<Attribute> list = new List<Attribute>();
            bool flag = false;
            foreach (Attribute attribute in propertyDescriptor.Attributes)
            {
                ReadOnlyAttribute readonlyAttribute = attribute as ReadOnlyAttribute;
                if (readonlyAttribute != null && !readonlyAttribute.IsReadOnly )
                {
                    list.Add(new ReadOnlyAttribute(true));
                    flag = true;
                }
                else if( !(attribute is EditorAttribute ))
                {
                    list.Add(attribute);
                }
            }
            if( !flag)
                list.Add(new ReadOnlyAttribute(true));

            properties.Add( new ElementPropertyDescriptor(this, propertyDescriptor.ModelElement, propertyDescriptor.DomainPropertyInfo, list.ToArray()));
            properties.Remove(propertyDescriptor);
        }

        protected void SetHidden(PropertyDescriptorCollection properties, Guid propertyInfoId)
        {
            var propertyDescriptor = FindPropertyDescriptoy(properties, propertyInfoId) as ElementPropertyDescriptor;
            Guard.AssumeNotNull(propertyDescriptor, "propertyDescriptor");

            List<Attribute> list = new List<Attribute>();
            bool flag = false;
            foreach (Attribute attribute in propertyDescriptor.Attributes)
            {
                BrowsableAttribute browsableAttribute = attribute as BrowsableAttribute;
                if (browsableAttribute != null && browsableAttribute.Browsable)
                {
                    list.Add(new BrowsableAttribute(false));
                    flag = true;
                }
                else 
                {
                    list.Add(attribute);
                }
            }
            if (!flag)
                list.Add(new BrowsableAttribute(false));

            properties.Add(new ElementPropertyDescriptor(this, propertyDescriptor.ModelElement, propertyDescriptor.DomainPropertyInfo, list.ToArray()));
            properties.Remove(propertyDescriptor);
        }

        /// <summary>
        /// Finds the property descriptoy.
        /// </summary>
        /// <param name="properties">The properties.</param>
        /// <param name="propertyInfoId">The property info id.</param>
        /// <returns></returns>
        private static PropertyDescriptor FindPropertyDescriptoy(PropertyDescriptorCollection properties, Guid propertyInfoId)
        {
            foreach (PropertyDescriptor descriptor in properties)
            {
                ElementPropertyDescriptor descriptor2 = descriptor as ElementPropertyDescriptor;
                if ((descriptor2 != null) && (descriptor2.DomainPropertyInfo.Id == propertyInfoId))
                {
                    return descriptor2;
                }
            }
            return null;
        }
    }
}
